package com.example.data.permission.url;

import cn.hutool.core.util.ClassUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.NonNull;

import java.lang.reflect.Method;

/**
 * Created by TD on 2021/8/9
 * 访问控制AOP，对URL进行拦截
 */
@Aspect
public class PreAuthorizationAspect implements ApplicationContextAware {

    private final static PreAuthorizationRootObject preAuthorizationRootObject=new PreAuthorizationRootObject();
    private final static ExpressionParser expressionParser= new SpelExpressionParser();


    /**
     * 拦截方法及类上的AccessControl注解
     */
    @Around("@annotation(preAuthorization) || " + "@within(preAuthorization)")
    public Object preAuth(ProceedingJoinPoint point, PreAuthorization preAuthorization) throws Throwable {
        StandardEvaluationContext context = new StandardEvaluationContext(preAuthorizationRootObject);
        context.setBeanResolver(new BeanFactoryResolver(applicationContext));
        String sPelValue = preAuthorization.value();
        Expression expression = expressionParser.parseExpression(sPelValue);
        Boolean value = expression.getValue(context, Boolean.class);
        if (value){
            return point.proceed();
        }
        return new SecurityException(StatusCodeEnum.ACCESS_DENIED);
    }

    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(@NonNull  ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
